#define _CRT_SECURE_NO_WARNINGS 1

#include<iostream>
#include<assert.h>
using namespace std;
namespace yan
{
	
	class string 
	{
	public:
		friend    ostream& operator<<( ostream& _cout, const string& s);
		typedef   char* iterator;
		typedef   char* reverse_iterator;

		// 构造
		string(const char* str = "")
		{
			if (str == nullptr)
				str = "";

			_size = strlen(str);
			_str = new char[_size + 1];
			strcpy(_str, str);
			_capacity = _size;
		}
		string(const string& s)
			:_str (new char[strlen(s._str) + 1])
			, _size(strlen(s._str))
			, _capacity (_size)
		{
			strcpy(_str, s._str);
		}
		/*		string(const string& s)
			: _str(nullptr)
			, _size(0)
			, _capacity(0)
		{
			string strTemp(s._str);
			this->swap(strTemp);
		}
		*/

		string(size_t n, char ch) 
			:_str(new char[n + 1])
			,_size(n)
			,_capacity(n)
		{

			memset(_str, ch, n);
			_str[n] = '\0'; // 一定要记得此步操作
		}
		string& operator=(string s) // 赋值运算符重载
		{
			if (this != &s)
			{
				delete[] _str;
				_str = new char[strlen(s._str) + 1];
				_size = strlen(s._str);
				_capacity = _size;
				strcpy(_str, s._str);
			}
			return *this;

		}
		/* 高级写法
		string& operator=(string s)
		{
			this->swap(s);
			return *this;
		}
		*/
		~string()
		{
			if (_str)
			{
				delete[] _str;
				_str = nullptr;
				_size = 0;
				_capacity = 0;
			}
		}
		///////////////////////////////////////
		// 迭代器
		iterator begin()
		{
			return _str;
		}

		iterator end()
		{
			return _str + _size;
		}

		reverse_iterator rbegin()
		{
			return end();
		}

		reverse_iterator rend()
		{
			return begin();
		}

		////////////////////////////////////////////
		// 容量
		size_t size()const
		{
			return _size;
		}

		size_t capacity()const
		{
			return _capacity;
		}

		bool empty()const
		{
			return 0 == _size;//是NULL 返回 1
		}

		void clear() // 容量此时不变
		{
			_size = 0;
			_str[0] = '\0';
		}
		void resize(size_t newsize, char ch)
		{
			size_t oldsize = size();

			if (newsize > oldsize)
			{
				if (newsize > _capacity)
				{
					reserve(newsize);
				}
				
				memset(_str + oldsize, ch ,newsize - oldsize);
				
			}
				_size = newsize;
				_str[_size] = '\0';

		}

		void resize(size_t newsize)
		{
			resize(newsize, 0);
		}

		void reserve(size_t newcapacity)
		{
			size_t oldcapacity = capacity();
			if (newcapacity > oldcapacity)
			{
				char* temp = new char[newcapacity + 1];
				strcpy(temp, _str);
				delete[] _str;
				_str = temp;
				_capacity = newcapacity;
			}
		}

		/////////////////////////////////////////////////
		// 元素访问

		char& operator[](size_t index) //返回值是引用，因为我们有可能对其元素进行值的修改。
		{
			assert(index < _size);
			return _str[index];
		}

		 const char& operator[](size_t index)const //如果返回值不加 const ，会发现 this指针指向的s会变化,这是不被允许的
		{
			assert(index < _size);
			return _str[index];
		}

		////////////////////////////////////////
				////////////////////////////////////////
		// 修改
		void push_back(char ch)
		{
			if (_size == _capacity)
				reserve(_capacity * 2);

			_str[_size] = ch;
			_size++;
			_str[_size] = '\0';
		}
		
		string& operator+=(char ch)
		{
			push_back(ch);
			return *this;
		}


		//string& operator+=(const string& s)          // 173  173
		//{
		//	for (int i = 0; i < s.size(); ++i)
		//	{
		//		push_back(s._str[i]);
		//	}
		//	return *this;
		//	
		//}
		// 这个方法也可以 调用上面那个方法
		string& operator+=(const string& s)
		{
			*this += s._str;	// 复用下面的函数
			return *this;
		}

		string& operator+=(const char* s)
		{
			size_t len = strlen(s);
			char* temp = new char[_size + len + 1]; // 总空间大小
			strcpy(temp, _str);
			strcat(temp, s);

			_size += len;
			delete[] _str;
			_str = temp;
			_capacity = _size;
			return *this;
		}
		////////////////////////////////////
		// 特殊操作
		const char* c_str()const // c_str 返回的是 string对象 存储空间的地址
		{
			return _str;
		}

		size_t find(char ch, size_t pos = 0)
		{
			for (size_t i = pos; i < _size; ++i)
			{
				if (_str[i] == ch)
					return i;
			}

			return npos;
		}

		size_t rfind(char ch, size_t pos = npos) // npos 是一个很大的数字
		{
			pos = pos < _size ? pos : _size - 1;
			for (int i = pos; i >= 0; --i)
			{
				if (_str[i] == ch)
					return i;
			}

			return npos; //没找见
		}

		string substr(size_t pos = 0, size_t n = npos) //从哪里开始找，找几个
		{
			if (n == npos)
				n = _size;

			if (pos + n >= _size)
			{
				n = _size - pos;
			}

			char* temp = new char[n + 1];
			strncpy(temp, _str + pos, n);
			temp[n] = '\0';

			string strRet(temp);
			delete[] temp;
			return strRet;
		}
		////////////////////////////////////
//
		void swap(string& s)
		{
			std::swap(_str, s._str);
			std::swap(_size, s._size);
			std::swap(_capacity, s._capacity);
		}

	private:
		char* _str;
		size_t _size;
		size_t _capacity;

	public:
		static size_t npos;

	};
	size_t string::npos = -1;

	ostream& operator<<(ostream& _cout, const string& s)
	{
		_cout << s._str;
		return _cout;
	}

}
void TestString1()
{
	yan::string s1;
	yan::string s2("hello");
	yan::string s3(s2);
	yan::string s4(10, 'A');

	cout << s2 << endl;

	for (size_t i = 0; i < s3.size(); ++i)
	{
		cout << s3[i];
	}
	cout << endl;

	for (auto e : s4)
		cout << e;
	cout << endl;

	auto it = s4.begin();
	while (it != s4.end())
	{
		cout << *it;
		++it;
	}
	cout <<endl;
    /*
    auto rit = s2.rbegin();
	do
	{
		--rit;
		cout << *rit;
		
	} while (rit != s2.rend());
	cout << endl;
    */
}

void TestString2()
{
	yan::string s("hello");


	s.clear();
	cout << s.size() << endl;
	cout << s.capacity() << endl;

	if (s.empty())
	{
		cout << "ok" << endl;
	}
	else
	{
		cout << "error" << endl;
	}
}

void TestString3()
{
	yan::string s("hello");
	s.reserve(10);
	cout << s.size() << endl;
	cout << s.capacity() << endl;

	s.reserve(20);
	cout << s.size() << endl;
	cout << s.capacity() << endl;

	s.reserve(15);
	cout << s.size() << endl;
	cout << s.capacity() << endl;

	s.reserve(5);
	cout << s.size() << endl;
	cout << s.capacity() << endl;
}

void TestString4()
{
	yan::string s("hello");
	s.resize(10, '!');
	cout << s.size() << endl;
	cout << s.capacity() << endl;
	cout << s << endl;

	s.resize(20, 'A');
	cout << s.size() << endl;
	cout << s.capacity() << endl;
	cout << s << endl;

	s.resize(15);
	cout << s.size() << endl;
	cout << s.capacity() << endl;
	cout << s << endl;

	s.resize(5);
	cout << s.size() << endl;
	cout << s.capacity() << endl;
	cout << s << endl;
}

void TestString5()
{
	yan::string s1("hello");
	s1[0] = 'H';

	const yan::string s2(s1);
	//cout << s2[0]<< endl;

	// s2[0] = 'n'; // 如果返回值不加 const ，可以试试这个语句，会发现s2 会变化
	//cout << s2 << endl;
	cout << s2[0] << endl;
}

void TestString6()
{
	yan::string s("hello");
	s.push_back('!');
	cout << s << endl;

	s += "world";
	cout << s << endl;


	yan::string ss("!!!");
	s += ss;
	cout << s << endl;
}

void TestString7()
{
	yan::string s("hellohellohello");
	size_t pos = 0;
	while (true)
	{
		pos = s.find('h', pos); //找不见返回 npos
		if (pos == yan::string::npos)
			break;

		cout << pos << endl;
		pos++;
	}
}

void TestString8()
{
	yan::string s("aaabbbbbccc.txt");
	int start = s.find('a');
	int end = s.rfind('a'); //  不论是从前往后 还是从后往前 ，找元素的位置都是不变的，从 0 到 size-1。
	yan::string ret = s.substr(start, end - start + 1);
	cout << ret << endl;

	cout << s.substr(s.rfind('.') + 1) << endl;
}

int main()
{
	// TestString1();
	//TestString2();
	//TestString3();
	//TestString4();
	//TestString5();
	//TestString6();
	//TestString7();
	//TestString8();
	_CrtDumpMemoryLeaks();
	return 0;
}
